﻿using PluginCore;
using System.Reflection;

namespace PluginConsoleApp
{
    internal class Program
    {
        //https://github.com/natemcmaster/DotNetCorePlugins
        static void Main(string[] args)
        {
            Console.WriteLine("Hello, World!");
            do
            {
                Console.WriteLine("Start...");

                Running();

                Console.WriteLine("End...");
            } while (Console.ReadKey().Key == ConsoleKey.Enter);

            Console.WriteLine("Over");
        }

        static Type INTERFACE_TYPE = typeof(IPluginCore);

        static void Running()
        {
            var pluginId = "TestPlugin";
            var path = "D:\\Study\\AspNetCoreSample\\src\\Plugin\\TestPlugin\\bin\\Debug\\net6.0\\TestPlugin.dll";

            var pluginContext = Pack(pluginId, path);
            var assembly = pluginContext.Assemblies.Where(a => a.FullName?.StartsWith(pluginId) ?? false).FirstOrDefault();
            if (assembly == default)
            {
                Console.WriteLine("Assembly Is Null");
                return;
            }

            var type = GetInstanceType(assembly);
            if (type == default)
            {
                Console.WriteLine("Type Is Null");
                return;
            }

            var instance = Activator.CreateInstance(type);
            if (instance is IPluginCore pluginCore)
            //if (instance is IPluginCore)
            {
                //var pluginCore= instance as IPluginCore;
                var result = pluginCore.Running(DateTime.Now.ToString());
                Console.WriteLine($"{DateTime.Now}:{result}");

                Console.WriteLine($"按下 {nameof(ConsoleKey.Enter)} 开始卸载");
                if (Console.ReadKey().Key == ConsoleKey.Enter)
                {
                    Console.WriteLine("开始卸载。。。");
                    pluginContext.Unload();
                    Console.WriteLine("卸载成功。。。");
                }

                return;
            }

            Console.WriteLine("instance Not Convert {TypeName}", nameof(IPluginCore));
        }

        static Type? GetInstanceType(Assembly assembly)
        {
            foreach (var type in assembly.ExportedTypes)
            {
                if (type.BaseType == INTERFACE_TYPE)
                {
                    if (!type.IsAbstract && !type.IsInterface)
                    {
                        return type;
                    }
                }
                else
                {
                    foreach (var iType in type.GetInterfaces())
                    {
                        if (INTERFACE_TYPE.IsAssignableFrom(iType))
                        {
                            if (!type.IsAbstract && !type.IsInterface)
                            {
                                return type;
                            }
                        }

                        //if (iType.FullName == INTERFACE_TYPE.FullName)
                        //{
                        //    if (!type.IsAbstract && !type.IsInterface)
                        //    {
                        //        return type;
                        //    }
                        //}
                    }
                }
            }
            return default;
        }

        //object ResolveUnregistered(Type type)
        //{
        //    Exception innerException = null;
        //    foreach (var constructor in type.GetConstructors())
        //    {
        //        try
        //        {
        //            //try to resolve constructor parameters
        //            var parameters = constructor.GetParameters().Select(parameter =>
        //            {
        //                //var service = Resolve(parameter.ParameterType);
        //                var service = _serviceProvider.GetService(parameter.ParameterType);
        //                if (service == null)
        //                    throw new Exception("Unknown dependency");
        //                return service;
        //            });

        //            //all is ok, so create instance
        //            return Activator.CreateInstance(type, parameters.ToArray());
        //        }
        //        catch (Exception ex)
        //        {
        //            innerException = ex;
        //        }
        //    }

        //    throw new Exception("No constructor was found that had all the dependencies satisfied.", innerException);

        //}
        static IPluginContext Pack(string pluginId, string pluginPath)
        {
            var context = new PluginLoadContext(pluginId, pluginPath);

            var assemblyName = new AssemblyName(Path.GetFileNameWithoutExtension(pluginPath));
            var assembly = context.LoadFromAssemblyName(assemblyName);

            return context;
        }
    }
}